package service

import (
	"context"
	"encoding/json"
	"fmt"
	"strings"
	"time"

	"github.com/google/uuid"
	"go.uber.org/zap"

	"yanxue_ai_go/pkg/common/database"
	"yanxue_ai_go/pkg/common/logger"
	"yanxue_ai_go/services/agent/internal/models"
)

// KnowledgeAgentService 知识百科Agent服务
type KnowledgeAgentService struct {
	aiService *AIService
}

// NewKnowledgeAgentService 创建知识百科Agent服务
func NewKnowledgeAgentService(aiService *AIService) *KnowledgeAgentService {
	return &KnowledgeAgentService{
		aiService: aiService,
	}
}

// CreateKnowledgeAgent 创建知识百科Agent
func (s *KnowledgeAgentService) CreateKnowledgeAgent(ctx context.Context, req *CreateKnowledgeAgentRequest) (*models.KnowledgeAgent, error) {
	// 构建配置
	config := KnowledgeAgentConfig{
		Model:         req.Model,
		Temperature:   req.Temperature,
		MaxTokens:     req.MaxTokens,
		ResponseStyle: req.ResponseStyle,
		Categories:    req.Categories,
		Languages:     req.Languages,
		Prompts:       req.Prompts,
	}

	configJSON, err := json.Marshal(config)
	if err != nil {
		return nil, fmt.Errorf("failed to marshal config: %w", err)
	}

	categoriesJSON, _ := json.Marshal(req.Categories)
	languagesJSON, _ := json.Marshal(req.Languages)

	agent := &models.KnowledgeAgent{
		Name:          req.Name,
		Description:   req.Description,
		Type:          "knowledge",
		Status:        "active",
		Config:        string(configJSON),
		Model:         req.Model,
		Categories:    string(categoriesJSON),
		Languages:     string(languagesJSON),
		Difficulty:    req.Difficulty,
		MaxQuestions:  req.MaxQuestions,
		ResponseStyle: req.ResponseStyle,
		CreatedBy:     req.CreatedBy,
	}

	if err := database.DB.Create(agent).Error; err != nil {
		logger.Logger.Error("Failed to create knowledge agent", zap.Error(err))
		return nil, fmt.Errorf("failed to create knowledge agent: %w", err)
	}

	logger.Logger.Info("Knowledge agent created successfully",
		zap.Uint("agent_id", agent.ID),
		zap.String("name", agent.Name))

	return agent, nil
}

// StartKnowledgeSession 开始知识问答会话
func (s *KnowledgeAgentService) StartKnowledgeSession(ctx context.Context, req *StartKnowledgeSessionRequest) (*models.KnowledgeSession, error) {
	// 获取Agent
	var agent models.KnowledgeAgent
	if err := database.DB.First(&agent, req.AgentID).Error; err != nil {
		return nil, fmt.Errorf("agent not found: %w", err)
	}

	sessionID := uuid.New().String()
	session := &models.KnowledgeSession{
		AgentID:   req.AgentID,
		SessionID: sessionID,
		UserID:    req.UserID,
		Topic:     req.Topic,
		Category:  req.Category,
		Status:    "active",
		StartedAt: time.Now(),
	}

	if err := database.DB.Create(session).Error; err != nil {
		return nil, fmt.Errorf("failed to create session: %w", err)
	}

	logger.Logger.Info("Knowledge session started",
		zap.String("session_id", sessionID),
		zap.Uint("agent_id", req.AgentID))

	return session, nil
}

// AskQuestion 向知识百科Agent提问
func (s *KnowledgeAgentService) AskQuestion(ctx context.Context, req *AskQuestionRequest) (*AskQuestionResponse, error) {
	startTime := time.Now()

	// 获取Agent和会话信息
	var agent models.KnowledgeAgent
	if err := database.DB.First(&agent, req.AgentID).Error; err != nil {
		return nil, fmt.Errorf("agent not found: %w", err)
	}

	var session models.KnowledgeSession
	if req.SessionID != "" {
		if err := database.DB.Where("session_id = ?", req.SessionID).First(&session).Error; err != nil {
			return nil, fmt.Errorf("session not found: %w", err)
		}
	}

	// 解析Agent配置
	var config KnowledgeAgentConfig
	if err := json.Unmarshal([]byte(agent.Config), &config); err != nil {
		return nil, fmt.Errorf("failed to parse agent config: %w", err)
	}

	// 构建专业的知识百科提示词
	systemPrompt := s.buildKnowledgeSystemPrompt(agent, config, req)

	// 准备AI请求
	aiReq := ChatServiceRequest{
		Messages: []ChatServiceMessage{
			{Role: "system", Content: systemPrompt},
			{Role: "user", Content: req.Question},
		},
		ModelID:     fmt.Sprintf("openai-%s", config.Model),
		Temperature: &config.Temperature,
		MaxTokens:   &config.MaxTokens,
	}

	// 调用AI服务
	aiResp, err := s.aiService.Chat(ctx, aiReq)
	if err != nil {
		return nil, fmt.Errorf("AI service error: %w", err)
	}

	responseTime := int(time.Since(startTime).Milliseconds())
	answer := aiResp.Choices[0].Message.Content

	// 分析答案质量和分类
	category := s.analyzeQuestionCategory(req.Question)
	difficulty := s.analyzeQuestionDifficulty(req.Question, answer)
	confidence := s.calculateConfidence(answer, aiResp.Usage.TotalTokens)

	// 保存问题记录
	question := &models.KnowledgeQuestion{
		AgentID:      req.AgentID,
		SessionID:    req.SessionID,
		Question:     req.Question,
		Answer:       answer,
		Category:     category,
		Difficulty:   difficulty,
		Language:     req.Language,
		ModelUsed:    config.Model,
		TokensUsed:   aiResp.Usage.TotalTokens,
		ResponseTime: responseTime,
		Confidence:   confidence,
	}

	if err := database.DB.Create(question).Error; err != nil {
		logger.Logger.Error("Failed to save question", zap.Error(err))
	}

	// 更新会话话题
	if req.SessionID != "" && session.Topic == "" {
		database.DB.Model(&session).Update("topic", category)
	}

	response := &AskQuestionResponse{
		ID:            question.ID,
		Answer:        answer,
		Category:      category,
		Difficulty:    difficulty,
		Confidence:    confidence,
		ResponseTime:  responseTime,
		TokensUsed:    aiResp.Usage.TotalTokens,
		Suggestions:   s.generateSuggestions(category, req.Question),
		RelatedTopics: s.generateRelatedTopics(category, answer),
	}

	logger.Logger.Info("Knowledge question answered",
		zap.Uint("question_id", question.ID),
		zap.String("category", category),
		zap.Int("response_time", responseTime))

	return response, nil
}

// GetKnowledgeHistory 获取知识问答历史
func (s *KnowledgeAgentService) GetKnowledgeHistory(ctx context.Context, req *GetKnowledgeHistoryRequest) (*GetKnowledgeHistoryResponse, error) {
	var questions []models.KnowledgeQuestion
	query := database.DB.Model(&models.KnowledgeQuestion{})

	// 应用筛选条件
	if req.AgentID != 0 {
		query = query.Where("agent_id = ?", req.AgentID)
	}
	if req.SessionID != "" {
		query = query.Where("session_id = ?", req.SessionID)
	}
	if req.Category != "" {
		query = query.Where("category = ?", req.Category)
	}
	if req.Difficulty != "" {
		query = query.Where("difficulty = ?", req.Difficulty)
	}

	// 分页
	offset := (req.Page - 1) * req.PageSize
	var total int64
	query.Count(&total)

	if err := query.Offset(offset).Limit(req.PageSize).
		Order("created_at DESC").
		Find(&questions).Error; err != nil {
		return nil, fmt.Errorf("failed to get knowledge history: %w", err)
	}

	// 转换模型数据为响应格式
	questionInfos := make([]KnowledgeQuestionInfo, len(questions))
	for i, q := range questions {
		questionInfos[i] = KnowledgeQuestionInfo{
			ID:           q.ID,
			Question:     q.Question,
			Answer:       q.Answer,
			Category:     q.Category,
			Difficulty:   q.Difficulty,
			Language:     q.Language,
			ModelUsed:    q.ModelUsed,
			TokensUsed:   q.TokensUsed,
			ResponseTime: q.ResponseTime,
			Confidence:   q.Confidence,
			Rating:       q.Rating,
			Feedback:     q.Feedback,
			IsHelpful:    q.IsHelpful,
			CreatedAt:    q.CreatedAt.Format("2006-01-02 15:04:05"),
		}
	}

	return &GetKnowledgeHistoryResponse{
		Questions: questionInfos,
		Total:     int(total),
		Page:      req.Page,
		PageSize:  req.PageSize,
	}, nil
}

// RateAnswer 对答案进行评分
func (s *KnowledgeAgentService) RateAnswer(ctx context.Context, req *RateAnswerRequest) error {
	var question models.KnowledgeQuestion
	if err := database.DB.First(&question, req.QuestionID).Error; err != nil {
		return fmt.Errorf("question not found: %w", err)
	}

	updates := map[string]interface{}{
		"rating":     req.Rating,
		"feedback":   req.Feedback,
		"is_helpful": req.IsHelpful,
	}

	if err := database.DB.Model(&question).Updates(updates).Error; err != nil {
		return fmt.Errorf("failed to update rating: %w", err)
	}

	logger.Logger.Info("Answer rated",
		zap.Uint("question_id", req.QuestionID),
		zap.Int("rating", req.Rating))

	return nil
}

// GetKnowledgeAnalytics 获取知识百科分析数据
func (s *KnowledgeAgentService) GetKnowledgeAnalytics(ctx context.Context, agentID uint, days int) (*KnowledgeAnalyticsResponse, error) {
	startDate := time.Now().AddDate(0, 0, -days)

	// 基础统计
	var totalQuestions, totalSessions, uniqueUsers int64
	database.DB.Model(&models.KnowledgeQuestion{}).
		Where("agent_id = ? AND created_at >= ?", agentID, startDate).
		Count(&totalQuestions)

	database.DB.Model(&models.KnowledgeSession{}).
		Where("agent_id = ? AND created_at >= ?", agentID, startDate).
		Count(&totalSessions)

	database.DB.Model(&models.KnowledgeSession{}).
		Where("agent_id = ? AND created_at >= ? AND user_id != ''", agentID, startDate).
		Distinct("user_id").
		Count(&uniqueUsers)

	// 平均响应时间
	var avgResponseTime float64
	database.DB.Model(&models.KnowledgeQuestion{}).
		Where("agent_id = ? AND created_at >= ?", agentID, startDate).
		Select("AVG(response_time)").
		Scan(&avgResponseTime)

	// 平均评分
	var avgRating float64
	database.DB.Model(&models.KnowledgeQuestion{}).
		Where("agent_id = ? AND created_at >= ? AND rating IS NOT NULL", agentID, startDate).
		Select("AVG(rating)").
		Scan(&avgRating)

	// 有用率
	var helpfulCount, ratedCount int64
	database.DB.Model(&models.KnowledgeQuestion{}).
		Where("agent_id = ? AND created_at >= ? AND is_helpful = true", agentID, startDate).
		Count(&helpfulCount)

	database.DB.Model(&models.KnowledgeQuestion{}).
		Where("agent_id = ? AND created_at >= ? AND is_helpful IS NOT NULL", agentID, startDate).
		Count(&ratedCount)

	helpfulRate := float64(0)
	if ratedCount > 0 {
		helpfulRate = float64(helpfulCount) / float64(ratedCount) * 100
	}

	// 分类统计
	categoryStats := s.getCategoryStatistics(agentID, startDate)
	difficultyStats := s.getDifficultyStatistics(agentID, startDate)

	response := &KnowledgeAnalyticsResponse{
		TotalQuestions:  int(totalQuestions),
		TotalSessions:   int(totalSessions),
		UniqueUsers:     int(uniqueUsers),
		AvgResponseTime: int(avgResponseTime),
		AvgRating:       float32(avgRating),
		HelpfulRate:     float32(helpfulRate),
		CategoryStats:   categoryStats,
		DifficultyStats: difficultyStats,
	}

	return response, nil
}

// buildKnowledgeSystemPrompt 构建知识百科系统提示词
func (s *KnowledgeAgentService) buildKnowledgeSystemPrompt(agent models.KnowledgeAgent, config KnowledgeAgentConfig, req *AskQuestionRequest) string {
	var categories []string
	json.Unmarshal([]byte(agent.Categories), &categories)

	var languages []string
	json.Unmarshal([]byte(agent.Languages), &languages)

	prompt := fmt.Sprintf(`你是一个专业的知识百科助手，名字叫"%s"。

角色定位：
- 知识渊博的百科专家
- 专业、准确、客观的回答问题
- 善于解释复杂概念，深入浅出

专业领域：%s

回答风格：%s
- detailed: 提供详细、全面的解释
- concise: 简洁明了，直击要点  
- educational: 教育性强，循序渐进

回答要求：
1. 准确性：确保信息的准确性和时效性
2. 结构化：使用清晰的段落和要点
3. 可理解：根据问题难度调整解释深度
4. 实用性：提供实际应用和例子
5. 引用：适当时提及权威来源

回答格式：
- 使用markdown格式
- 重要信息用**粗体**标注
- 复杂概念提供简单类比
- 必要时提供相关链接建议

特殊指令：
- 如遇不确定信息，明确标注"需要进一步验证"
- 涉及专业医学/法律建议时，建议咨询专业人士
- 保持中性立场，避免主观判断

当前对话语言：%s
请根据用户问题提供专业、准确的回答。`,
		agent.Name,
		strings.Join(categories, "、"),
		agent.ResponseStyle,
		req.Language)

	// 添加自定义提示词
	if len(config.Prompts) > 0 {
		prompt += "\n\n额外指导原则：\n"
		for _, customPrompt := range config.Prompts {
			prompt += "- " + customPrompt + "\n"
		}
	}

	return prompt
}

// analyzeQuestionCategory 分析问题分类
func (s *KnowledgeAgentService) analyzeQuestionCategory(question string) string {
	question = strings.ToLower(question)

	// 简单的关键词分类
	categories := map[string][]string{
		"科学技术": {"科学", "技术", "物理", "化学", "生物", "数学", "计算机", "工程"},
		"历史人文": {"历史", "文化", "艺术", "文学", "哲学", "宗教", "社会"},
		"地理自然": {"地理", "自然", "环境", "气候", "动物", "植物", "生态"},
		"医学健康": {"医学", "健康", "疾病", "药物", "营养", "心理", "运动"},
		"经济商业": {"经济", "商业", "金融", "投资", "市场", "管理", "创业"},
		"教育学习": {"教育", "学习", "学校", "考试", "技能", "培训", "方法"},
		"生活常识": {"生活", "日常", "家庭", "饮食", "出行", "购物", "娱乐"},
	}

	for category, keywords := range categories {
		for _, keyword := range keywords {
			if strings.Contains(question, keyword) {
				return category
			}
		}
	}

	return "综合知识"
}

// analyzeQuestionDifficulty 分析问题难度
func (s *KnowledgeAgentService) analyzeQuestionDifficulty(question, answer string) string {
	questionLen := len(question)
	answerLen := len(answer)

	// 基于问题长度和答案复杂度判断难度
	if questionLen < 20 && answerLen < 200 {
		return "easy"
	} else if questionLen < 50 && answerLen < 500 {
		return "medium"
	} else if questionLen < 100 && answerLen < 1000 {
		return "hard"
	}
	return "expert"
}

// calculateConfidence 计算置信度
func (s *KnowledgeAgentService) calculateConfidence(answer string, tokensUsed int) float32 {
	// 基于答案长度、结构化程度和tokens使用量计算置信度
	confidence := float32(0.5) // 基础置信度

	// 根据答案长度调整
	if len(answer) > 100 {
		confidence += 0.2
	}

	// 根据结构化程度调整
	if strings.Contains(answer, "**") || strings.Contains(answer, "##") {
		confidence += 0.1
	}

	// 根据tokens使用量调整
	if tokensUsed > 100 {
		confidence += 0.1
	}

	if confidence > 1.0 {
		confidence = 1.0
	}

	return confidence
}

// generateSuggestions 生成相关建议
func (s *KnowledgeAgentService) generateSuggestions(category, question string) []string {
	suggestions := []string{
		"您还想了解" + category + "领域的其他知识吗？",
		"相关概念可能需要进一步解释，请随时提问",
		"如需更深入了解，我可以提供更详细的解答",
	}
	return suggestions
}

// generateRelatedTopics 生成相关话题
func (s *KnowledgeAgentService) generateRelatedTopics(category, answer string) []string {
	// 简单的相关话题生成逻辑
	topics := []string{
		category + "的基础概念",
		category + "的发展历史",
		category + "的实际应用",
		category + "的前沿发展",
	}
	return topics
}

// getCategoryStatistics 获取分类统计
func (s *KnowledgeAgentService) getCategoryStatistics(agentID uint, startDate time.Time) map[string]int {
	var results []struct {
		Category string
		Count    int64
	}

	database.DB.Model(&models.KnowledgeQuestion{}).
		Select("category, COUNT(*) as count").
		Where("agent_id = ? AND created_at >= ?", agentID, startDate).
		Group("category").
		Find(&results)

	stats := make(map[string]int)
	for _, result := range results {
		stats[result.Category] = int(result.Count)
	}

	return stats
}

// getDifficultyStatistics 获取难度统计
func (s *KnowledgeAgentService) getDifficultyStatistics(agentID uint, startDate time.Time) map[string]int {
	var results []struct {
		Difficulty string
		Count      int64
	}

	database.DB.Model(&models.KnowledgeQuestion{}).
		Select("difficulty, COUNT(*) as count").
		Where("agent_id = ? AND created_at >= ?", agentID, startDate).
		Group("difficulty").
		Find(&results)

	stats := make(map[string]int)
	for _, result := range results {
		stats[result.Difficulty] = int(result.Count)
	}

	return stats
}
